
#ifndef RSpriteBatch_h
#define RSpriteBatch_h

// Riccsson includes.
#include <System/Object.h>
#include <System/ArgumentException.h>
#include <System/Text/StringBuilder.h>

// XNA includes.
#include "../RMatrix.h"
#include "../Vector2.h"
#include "../Rectangle.h"
#include "../RGame.h"
#include "GraphicsDevice.h"
#include "Effect/Effect.h"
#include "States/BlendState.h"
#include "GraphicsResource.h"
#include "SpriteSortMode.h"
#include "States/SamplerState.h"
#include "States/DepthStencilState.h"
#include "States/RasterizerState.h"
#include "SpriteBatcher.h"
#include "SpriteEffects.h"

namespace Riccsson
{
	namespace Xna
	{
		namespace Framework
		{
			namespace Graphics
			{
				// Not implemented.
				class SpriteFont {};

				class SpriteBatch
					: public GraphicsResource
				{
					bool _beginCalled;
					GC_PTR<BlendState> _blendState;
					SpriteSortMode _sortMode;

					System::Collections::Generic::List<GC_PTR<SpriteBatchItem>> m_spriteBatchItems;
					System::Collections::Generic::List<GC_PTR<SpriteBatchItem>> m_spriteBatchItemsOld;

					private: SpriteBatchItem* getSpriteBatchItem();

					public: SpriteBatch (GraphicsDevice* graphicsDevice);
	
					public: void Begin (SpriteSortMode sortMode, BlendState* blendState, SamplerState* samplerState, DepthStencilState* depthStencilState, RasterizerState* rasterizerState, Effect* effect, Matrix transformMatrix);

					public: void Begin (SpriteSortMode sortMode, BlendState* blendState, SamplerState* samplerState, DepthStencilState* depthStencilState, RasterizerState* rasterizerState);

					public: void Begin (SpriteSortMode sortMode, BlendState* blendState, SamplerState* samplerState, DepthStencilState* depthStencilState, RasterizerState* rasterizerState, Effect* effect);
						
					public: void Begin (SpriteSortMode sortMode, BlendState* blendState);

					public: void Begin ();

					public: void End ();
		
					void Setup();
		
					void CheckValid(Texture2D* texture);

					void CheckValid(SpriteFont* spriteFont, const Riccsson::System::String* text);

					void CheckValid(SpriteFont* spriteFont, Riccsson::System::Text::StringBuilder* text);

					public: void Draw (Texture2D* texture,
						const Vector2& position,
						const Riccsson::System::Nullable<Rectangle>& sourceRectangle,
						const Color& color,
						float rotation,
						const Vector2& origin,
						const Vector2& scale,
						SpriteEffects effect,
						float depth);

					public: void Draw (Texture2D* texture,
						const Vector2& position,
						const Riccsson::System::Nullable<Rectangle>& sourceRectangle,
						const Color& color,
						float rotation,
						const Vector2& origin,
						float scale,
						SpriteEffects effect,
						float depth);

					public: void Draw (Texture2D* texture,
						const Rectangle& destinationRectangle,
						const Riccsson::System::Nullable<Rectangle>& sourceRectangle,
						const Color& color,
						float rotation,
						const Vector2& origin,
						SpriteEffects effect,
						float depth);

					public: /*internal*/ void DrawInternal (Texture2D* texture,
						const Vector4& destinationRectangle,
						const Riccsson::System::Nullable<Rectangle>& sourceRectangle,
						const Color& color,
						float rotation,
						const Vector2& origin,
						SpriteEffects effect,
						float depth);

					public: void Draw(Texture2D* texture, const Vector2& position, const Riccsson::System::Nullable<Rectangle>& sourceRectangle, const Color& color);

					public: void Draw(Texture2D* texture, const Rectangle& destinationRectangle, const Riccsson::System::Nullable<Rectangle>& sourceRectangle, const Color& color);

					public: void Draw(Texture2D* texture, const Vector2& position, const Color& color);

					public: void Draw(Texture2D* texture, const Rectangle& rectangle, const Color& color);

					public: void DrawString(SpriteFont* spriteFont, Riccsson::System::String* text, Vector2& position, Color& color);

					public: void DrawString (
						SpriteFont* spriteFont, const Riccsson::System::String* text, Vector2& position, Color& color,
						float rotation, Vector2& origin, float scale, SpriteEffects effects, float depth);

					public: void DrawString (
						SpriteFont* spriteFont, const Riccsson::System::String* text, Vector2& position, Color& color,
						float rotation, Vector2& origin, Vector2& scale, SpriteEffects effect, float depth);

					public: void DrawString(SpriteFont* spriteFont, Riccsson::System::Text::StringBuilder* text, Vector2& position, Color& color);

					public: void DrawString (
						SpriteFont* spriteFont, Riccsson::System::Text::StringBuilder* text, Vector2& position, Color& color,
						float rotation, Vector2& origin, float scale, SpriteEffects effects, float depth);

					public: void DrawString (
						SpriteFont* spriteFont, Riccsson::System::Text::StringBuilder* text, Vector2& position, Color& color,
						float rotation, Vector2& origin, Vector2& scale, SpriteEffects effect, float depth);

					protected: override void Dispose(bool disposing);
				};
			}
		}
	}
}

#endif
